package edu.uoc.tds.pec4.server.bbdd;

import edu.uoc.tds.pec4.common.RemotoInterface;
import java.sql.SQLException;
import java.sql.Statement;
import java.rmi.RemoteException;
import java.sql.ResultSet;
import java.text.NumberFormat;
import edu.uoc.tds.pec4.i18n.GestorIdiomas;
import edu.uoc.tds.pec4.model.Estudiante;
import edu.uoc.tds.pec4.model.Medallero;
import edu.uoc.tds.pec4.model.ParticipantesEstadistica;
import edu.uoc.tds.pec4.model.PruebaDetalleEstadistico;
import edu.uoc.tds.pec4.model.ResultadoEstudiante;
import edu.uoc.tds.pec4.model.TipoRonda;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;

/**
 *
 * @author TdsSoft
 */
public class GestorEstadistica {
     RemotoInterface remoto;
     String schema;
     int numAciertos = 0;
     int numBlancos = 0;
     int numErrores = 0;
     int numPreguntas = 0;

     
     /**
      * 
      * @param remoto
      * @throws RemoteException
      */
     public GestorEstadistica(RemotoInterface remoto) throws RemoteException{
        this.remoto = remoto;
        this.schema=remoto.getSchema();
        
    }
    
    
     /**
      * Pruebas creadas
      * @return int
      * @throws RemoteException
      * Obtiene el número de pruebas creadas que no esten de baja
      */
     public int numPruebas () throws RemoteException{
    	int num = -1;
       
        try {
            Statement sentencia = this.remoto.getConexion().createStatement(); 
            String consulta = "SELECT COUNT(*) FROM " + this.schema + ".PRUEBA WHERE fecha_baja is null;";
            ResultSet rs = sentencia.executeQuery(consulta);
            if (rs.next()){
            	num = (rs.getInt("COUNT"));
            }
            sentencia.close();
            
        }catch (SQLException e) {
               JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_numPruebas"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        } catch (Exception e) {
              JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_numPruebas"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        }
        return num;
    }
    
     /**
      * Pruebas en curso
      * @return int
      * @throws RemoteException
      * Obtiene el número de pruebas en curso. Es decir, aquellas que estan en estado 3 (competición previa),
      * 4 (competición final) ó 5 (publicación de clasificación previa)
      */
     public int pruebasEnCurso()  throws RemoteException{
    	int num = -1;
       
        try {
            Statement sentencia = this.remoto.getConexion().createStatement();
            String consulta = "SELECT COUNT(*) FROM " + this.schema + ".PRUEBA WHERE (id_estado_prueba = 3 " + 
		"OR id_estado_prueba = 4 OR id_estado_prueba = 5) AND  fecha_baja is null;";
            ResultSet rs = sentencia.executeQuery(consulta);
            if (rs.next()){
            	num = (rs.getInt("COUNT"));
            }
            sentencia.close();
        }catch (SQLException e) {
              JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_numPruebasEnCurso"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        } catch (Exception e) {
              JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_numPruebasEnCurso"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        }
            
        return num;
    }
    
     /**
      * Pruebas finalizadas
      * @return int
      * @throws RemoteException
      * Obtiene el número de pruebas con estado 6. Es decir las que se encuentran en estado de otorgar 
      * la clasificación final.
      */
     public int pruebasFinalizadas()  throws RemoteException{
    	int num = -1;
       
        try {
            Statement sentencia = this.remoto.getConexion().createStatement(); 
            String consulta = "SELECT COUNT(*) FROM " + this.schema + ".PRUEBA WHERE id_estado_prueba = 6 " +
                               "AND  fecha_baja is null;";
            ResultSet rs = sentencia.executeQuery(consulta);
            if (rs.next()){
            	num = (rs.getInt("COUNT"));
            }
            sentencia.close();
        }catch (SQLException e) {
               JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_numPruebasFinalizadas"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
            } catch (Exception e) {
              JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_numPruebasFinalizadas"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
            }
            return num;
     }
    
    /**
     * Estudiantes inscritos
     * @return int
     * @throws RemoteException
     * Obtiene el número de estudiantes que figuran en la tabla inscripción, siendo NULL la fecha de baja
      * y con independencia del número de pruebas en las que está inscrito. 
     */
    public int estudiantesInscritos()  throws RemoteException{
    	int num = -1;
        try {
            Statement sentencia = this.remoto.getConexion().createStatement();
            String consulta = 
                "SELECT COUNT(*) " +  
                "FROM (SELECT DISTINCT id_usuario " +
                       "FROM " + this.schema + ".inscripcion " + 
                       "WHERE fecha_baja is null) as a;";
            
            ResultSet rs = sentencia.executeQuery(consulta);
            if (rs.next()){
            	num = (rs.getInt("COUNT"));
            }
            sentencia.close();
        }catch (SQLException e) {
               JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_estudiantesInscritos"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        } catch (Exception e) {
              JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_estudiantesInscritos"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        }
        return num;
     }

 /**
  * Medallas
  * @return int
  * @throws RemoteException
  * Se obtiene el número de medallas otorgadas hasta el momento de la consulta (tipo de ronda final
  * en posiciones 1ª, 2ª o 3ª.
  */
 public int medallas() throws RemoteException{
    	int num = -1;
       
        try {
            Statement sentencia = this.remoto.getConexion().createStatement();
            String consulta = "SELECT COUNT(*) FROM " + this.schema + 
                    ".InscripcionRonda WHERE id_tipo_ronda = 1 AND clasificacion between 1 and 3;";
            ResultSet rs = sentencia.executeQuery(consulta);
            if (rs.next()){
            	num = (rs.getInt("COUNT"));
            }
            sentencia.close();
            }catch (SQLException e) {
               JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_medallas"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
            } catch (Exception e) {
              JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_medallas"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
            }
            return num;
    }

    /**
     * Universidades participantes
     * @return int
     * @throws RemoteException
     * Obtiene las distintas universidades que tienen estudiantes inscritos sin haberse dado de baja 
     * (los estudiantes) de la competición.
     */
    public int universidadesParticipantes()  throws RemoteException{
    	int num = -1;
        try {
            Statement sentencia = this.remoto.getConexion().createStatement();
            String consulta = 
                        "SELECT COUNT (*) " +  
                        "FROM (SELECT DISTINCT id_universidad " +
                               "FROM " + this.schema + ".usuario u " + 
                                    "INNER JOIN " + this.schema + ".inscripcion i " + 
                                    "ON u.id_usuario = i.id_usuario " +
                                "WHERE I.fecha_baja is null) as a;";
            ResultSet rs = sentencia.executeQuery(consulta);
            if (rs.next()){
            	num = (rs.getInt("COUNT"));
            }
            sentencia.close();
        }catch (SQLException e) {
               JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_universidadesParticipantes"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        } catch (Exception e) {
              JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_universidadesParticipantes"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        }
        return num;
    }

 /**
  * Numero de pruebas (denominador) de media de estudiantes inscritos por prueba
  * @return int
  * @throws RemoteException
  * Se obtienen el número de pruebas que tienen estudiantes inscritos y estan 
  * cerradas y no estan de baja
  */
 public int pruebasInscripcion() throws RemoteException{
    	int num = -1;
        try {
            Statement sentencia = this.remoto.getConexion().createStatement(); 
            String consulta =             
                    "SELECT COUNT(*) numPrueba " + 
                    "FROM (SELECT DISTINCT p.id_prueba " +
                           "FROM " + this.schema + ".inscripcion i " +
                                "INNER JOIN " + this.schema + ".prueba p " +
                                "ON i.id_prueba = p.id_prueba " +
                           "WHERE i.fecha_baja is null " +
                           "AND p.fecha_baja is null " +
                           "AND p.id_estado_prueba = 6) as a;";            
             ResultSet rs = sentencia.executeQuery(consulta);
            if (rs.next()){
            	num = (rs.getInt("numPrueba"));
            }
            sentencia.close();
        }catch (SQLException e) {
               JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_inscripciones"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
            } catch (Exception e) {
              JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_inscripciones"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
            }
            return num;
    }
    
    /**
     * Numero de inscripciones (numerador) de media de estudiantes inscritos por prueba
     * @return int
     * @throws RemoteException
     * Se obtiene el número de inscripciones en pruebas activas y cerradas 
     */
    public int inscritosPruebasConCierre() throws RemoteException{
    	int num = -1;
        try {
            Statement sentencia = this.remoto.getConexion().createStatement();
            String consulta =             
                    "SELECT COUNT(*) numUsuario " + 
                    "FROM (SELECT DISTINCT i.id_prueba, i.id_usuario " +
                           "FROM " + this.schema +".inscripcion i " +
                                "INNER JOIN  " + this.schema + ".prueba p " +
                                "ON i.id_prueba = p.id_prueba " +
                           "WHERE i.fecha_baja is null " +
                           "AND p.fecha_baja is null " +
                           "AND p.id_estado_prueba = 6) as a;";
            ResultSet rs = sentencia.executeQuery(consulta);
            if (rs.next()){
            	num = (rs.getInt("numUsuario"));
            }
            sentencia.close();
        }catch (SQLException e) {
               JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_inscritosPruebasConCierre"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
            } catch (Exception e) {
              JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_inscritosPruebasConCierre"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
            }
            return num;
    }    

    /**
     * Participacion sobre inscritos: Numero de inscritos  
     * 
     * @return String
     * @throws RemoteException
     * Se obtiene por un lado el número de inscripciones en pruebas finalizada y por otro
     * el número de usuarios que han participado en una prueba finalizada, tanto en la 
     * ronda preliminar, como en la fase final
     * El resultado siempre que no sea cero el número de inscripciones, será participantes *100/inscripciones.
     * En caso contrarrio será un guión
     */
    public String participantesDeInscritos() throws RemoteException{ //Mirar cambio de tipo de variable retornada
        String salida = "-";
    	int num = -1;
        try { //Denominador: inscritos
            Statement sentencia = this.remoto.getConexion().createStatement();
            String consulta =             
                      "SELECT COUNT (*) " +
                      "FROM (SELECT DISTINCT i.id_prueba, i.id_usuario " + 
                             "FROM  " + this.schema + ".inscripcion i " +
                                   "INNER JOIN  " + this.schema + ".prueba p " +
                                   "ON i.id_prueba = p.id_prueba " + 
                             "WHERE p.id_estado_prueba=6) as a;";
            ResultSet rs = sentencia.executeQuery(consulta);
            if (rs.next()){
            	num = (rs.getInt("COUNT"));
            }
            sentencia.close();
        }catch (SQLException e) {
              JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_participantesDeInscritos_Inscritos"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        } catch (Exception e) {
              JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_participantesDeInscritos_Inscritos"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        }
        if (num>0){
            int numN = -1;
            try { //Numerador: Pariticipantes
                Statement sentencia = this.remoto.getConexion().createStatement();
                String consulta =             
                    "SELECT COUNT (*) " + 
                    "FROM (SELECT DISTINCT i.id_prueba, i.id_usuario " +
                          "FROM " + this.schema + ".inscripcionRonda i " +
                               "INNER JOIN  " + this.schema + ".prueba p " + 
                               "ON i.id_prueba = p.id_prueba " + 
                               "INNER JOIN (SELECT id_prueba " +
                                            "FROM  " + this.schema + ".prueba " +
                                            "WHERE id_estado_prueba = 6) as pp " +
                               "ON p.id_prueba = pp.id_prueba " +
                          "WHERE i.fecha_presentacion IS NOT NULL) as a;";
                ResultSet rs = sentencia.executeQuery(consulta);
                if (rs.next()){
                    numN = (rs.getInt("COUNT"));
                }
                sentencia.close();
                double d = numN * 100.0 / num;
                NumberFormat nf = NumberFormat.getInstance();
                nf.setMaximumFractionDigits(2);
                nf.setMinimumFractionDigits(2);
                salida = nf.format(d) + "%";
            }catch (SQLException e) {
                  JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_participantesDeInscritos_Participantes"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
            } catch (Exception e) {
                  JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_participantesDeInscritos_Participantes"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
            }
        }
        return salida;
    }
   
    /**
     * Puntuación media
     * @return double
     * @throws RemoteException
     * Se obtiene la puntuación media 
     */
    public double puntuacionMedia() throws RemoteException{
    	double num = -1;
        try {
            Statement sentencia = this.remoto.getConexion().createStatement();
            String consulta = "SELECT AVG(i.puntuacion) FROM " + this.schema + ".inscripcionRonda i;";
            ResultSet rs = sentencia.executeQuery(consulta);
            if (rs.next()){
            	num = (rs.getDouble("AVG"));
            }
            sentencia.close();
        }catch (SQLException e) {
               JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_puntuacionMedia"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        } catch (Exception e) {
              JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_puntuacionMedia"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        }
            return num;
    }

    /**
     * Numero medio de preguntas
     * @return Double
     * @throws RemoteException
     * Se obtiene la media de preguntas
     */
    public double preguntasMedias() throws RemoteException{
    	double num = -1;
        try {
            Statement sentencia = this.remoto.getConexion().createStatement();
            String consulta = "SELECT AVG(r.numero_preguntas) FROM " + this.schema + ".Ronda r;";
            ResultSet rs = sentencia.executeQuery(consulta);
            if (rs.next()){
            	num = (rs.getDouble("AVG"));
            }
            sentencia.close();
        }catch (SQLException e) {
               JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_preguntasMedias"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        } catch (Exception e) {
              JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_preguntasMedias"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        }
        return num;
    }
    
    /**
     * Acierto sobre preguntas
     * @return String
     * @throws RemoteException
     * Se obtiene el número de preguntas y las cadenas de cada ronda de las respuestas del estudiante
     * y de las respuestas correctas. Despues con la ayuda de la función comparaRespuestas se obtiene
     * el numero de aciertos y el número de preguntas
     * Se retorna aciertos*100/preguntas
     */
    public String aciertosPreguntas() throws RemoteException{
        numAciertos = 0;
        numBlancos = 0;
        numErrores = 0;
        numPreguntas = 0;

        String salida = "-";
        try {
            Statement sentencia = this.remoto.getConexion().createStatement();
            String consulta = "SELECT r.numero_preguntas, r.respuestas, ir.respuestas_estudiantes FROM " + this.schema + 
                    ".ronda r INNER JOIN " + this.schema + ".inscripcionRonda ir ON ir.id_prueba = r.id_prueba " +
                    "WHERE numero_preguntas IS NOT NULL;";
            ResultSet rs = sentencia.executeQuery(consulta);
            while(rs.next()){
                int nP = rs.getInt("numero_preguntas");
                String rC = rs.getString("respuestas");
                String rE = rs.getString("respuestas_estudiantes");
                comparaRespuestas(rE, rC, nP);
            }
            sentencia.close();
            if (numPreguntas > 0){
                double d = numAciertos * 100.0 / numPreguntas;
                NumberFormat nf = NumberFormat.getInstance();
                nf.setMaximumFractionDigits(2);
                nf.setMinimumFractionDigits(2);
                salida = nf.format(d) + "%";
            }
        }catch (SQLException e) {
               JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_preguntasMedias"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_preguntasMedias"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        }
            return salida;
    }

    /**
     * Resultado medallero
     * @return List<Medallero>
     * @throws RemoteException
     * Se obtienen las universidades con su descripción y se cruzan con subselect que extraen 
     * el id_universidad y el número de medallas de oro (número de estudiantes de esa universidad que en 
     * la fase final tienen la clasificación = 1); plata (número de estudiantes de esa universidad que en 
     * la fase final tienen la clasificación = 2); bonce (número de estudiantes de esa universidad que en 
     * la fase final tienen la clasificación = 3)
     */
    public List<Medallero> obtenerMedallero()  throws RemoteException{
        List<Medallero> medallero = new ArrayList<Medallero>();
        try {
            Statement sentencia = this.remoto.getConexion().createStatement();
            String consulta =
                "SELECT u.id_universidad, u.nombre_universidad, COALESCE(o.oro, 0) oro, " +
                    "COALESCE(p.plata, 0) plata, " + "COALESCE(b.bronce, 0) bronce, " +
                    "COALESCE(o.oro, 0) + COALESCE(p.plata, 0) + COALESCE(b.bronce, 0) total " +
                "FROM ((" + this.schema + ".universidad u " +
                     "left outer join " +
                             "(SELECT un.id_universidad, COUNT(ir.clasificacion) oro " + 
                             "FROM " + this.schema + ".universidad un INNER JOIN " + this.schema + ".usuario us " + 
                                   "ON un.id_universidad = us.id_universidad " + 
                                   "INNER JOIN " + this.schema + ".inscripcionRonda ir " + 
                                   "ON us.id_usuario = ir.id_usuario " +
                             "WHERE ir.clasificacion = 1 and ir.id_tipo_ronda = 1 " +
                             "GROUP BY un.id_universidad) as o " +
                     "ON u.id_universidad = o.id_universidad) " +
                     "LEFT OUTER JOIN " +
                             "(SELECT un.id_universidad, COUNT(ir.clasificacion) plata " +
                             "FROM " + this.schema + ".universidad un INNER JOIN " + this.schema + ".usuario us " +
                                   "ON un.id_universidad = us.id_universidad " + 
                                   "INNER JOIN " + this.schema + ".inscripcionRonda ir " + 
                                   "ON us.id_usuario = ir.id_usuario " +
                             "WHERE ir.clasificacion = 2 and ir.id_tipo_ronda = 1 " +
                             "GROUP BY un.id_universidad) as p " +	           
                     "ON u.id_universidad = p.id_universidad) " +
                     "LEFT OUTER JOIN " +
                             "(SELECT un.id_universidad, COUNT(ir.clasificacion) bronce " +
                             "FROM " + this.schema + ".universidad un INNER JOIN " + this.schema + ".usuario us " +
                                   "ON un.id_universidad = us.id_universidad " +
                                   "INNER JOIN " + this.schema + ".inscripcionRonda ir " +
                                   "ON us.id_usuario = ir.id_usuario " +
                             "WHERE ir.clasificacion = 3 and ir.id_tipo_ronda = 1 " +
                             "GROUP BY un.id_universidad) as b " +
                     "ON u.id_universidad = b.id_universidad " +
                "WHERE o.oro IS NOT NULL or p.plata IS NOT NULL or b.bronce IS NOT NULL " +
                "ORDER BY total DESC;";
            ResultSet rs = sentencia.executeQuery(consulta);
            while(rs.next()){
                Medallero m = new Medallero();
                m.setIdUniversidad(rs.getInt("id_universidad"));
                m.setNombreUniversidad(rs.getString("nombre_universidad"));
                m.setMedallaOro(rs.getInt("oro"));
                m.setMedallaPlata(rs.getInt("plata"));
                m.setMedallaBronce(rs.getInt("bronce"));
                medallero.add(m);
            }
            sentencia.close();
        }catch (SQLException e) {
               JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_medallero"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_medallero"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        }
            return medallero;
    }

    /**
     * Resultados del estudiante
     * @param estudiante
     * @return List<ResultadoEstudiante>
     * @throws RemoteException
     * Se obtiene la lista de pruebas, el número de preguntas, la puntuación y la clasificación del
     * estudiante que se pasa como parámetro
     */
    public List<ResultadoEstudiante> obtenerResultadosEstudiante(Estudiante estudiante)  throws RemoteException{
        List<ResultadoEstudiante> resultadoEstudiante = new ArrayList<ResultadoEstudiante>();
        try {
            Statement sentencia = this.remoto.getConexion().createStatement();
            String consulta =
                "SELECT p.descripcion_prueba, r.id_tipo_ronda, r.numero_preguntas, ir.puntuacion, " + 
                       "ir.clasificacion || '\u00ba de ' || ira.numAlumnos clasificacion, " +
                       "CASE WHEN r.id_tipo_ronda = 0 and ir.clasificacion<11 THEN 'Clasificado' " +
                            "WHEN r.id_tipo_ronda = 1 and ir.clasificacion=1 THEN 'Oro' " +
                            "WHEN r.id_tipo_ronda = 1 and ir.clasificacion=2 THEN 'Plata' " +
                            "WHEN r.id_tipo_ronda = 1 and ir.clasificacion=3 THEN 'Bronce' " +
                       "END resultado " +
                "FROM " + this.schema + ".inscripcionRonda ir " + 
                   "INNER JOIN " + this.schema + ".Ronda r " +
                   "ON ir.id_prueba= r.id_prueba AND ir.id_tipo_ronda = r.id_tipo_ronda " +
                   "INNER JOIN " + this.schema + ".prueba p " +
                   "ON r.id_prueba = p.id_prueba " +
                   "INNER JOIN (" +
                       "SELECT id_tipo_ronda, id_prueba, COUNT(id_usuario) numAlumnos " +
                       "FROM " + this.schema + ".inscripcionRonda " +
                       "GROUP BY id_tipo_ronda, id_prueba) ira " +
                   "ON ir.id_prueba = ira.id_prueba AND ir.id_tipo_ronda = ira.id_tipo_ronda " +
                "WHERE ir.id_usuario = " + estudiante.getId_usuario() +
                " ORDER BY p.descripcion_prueba, r.id_tipo_ronda;";
            ResultSet rs = sentencia.executeQuery(consulta);
            while(rs.next()){
                ResultadoEstudiante rE = new ResultadoEstudiante();
                rE.setPrueba(rs.getString("descripcion_prueba"));
                rE.setTipo(TipoRonda.values()[rs.getInt("id_tipo_ronda")].toString());
                rE.setNumPregutas(rs.getInt("numero_preguntas"));
                rE.setPuntuacion(rs.getDouble("puntuacion"));
                rE.setClasificacion(rs.getString("clasificacion"));
                rE.setResultado(rs.getString("resultado"));
                resultadoEstudiante.add(rE);
            }
            sentencia.close();
        }catch (SQLException e) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_resultadoEstudiante"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_resultadoEstudiante"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        }
            return resultadoEstudiante;
    }

    /**
     * Lista de pruebas de la ventana de detalles
     * @return List<PruebaDetalleEstadistico>
     * @throws RemoteException
     * Se obtiene la lista de detalle de las pruebas/rondas (prueba, id_prueba, tipo_ronda, respuestas correctas, 
     * participantes, numero de preguntas, fecha de inicio y fecha de realización.
     */
    public List<PruebaDetalleEstadistico> obtenerPruebaDetalleEstadistico() throws RemoteException{
        List<PruebaDetalleEstadistico> pruebaDetalleEstadistico = new ArrayList<PruebaDetalleEstadistico>();
        try {
            Statement sentencia = this.remoto.getConexion().createStatement(); 
            String consulta =
                "SELECT r.id_prueba, r.id_tipo_ronda, r.respuestas, i.participantes, r.numero_preguntas, " +
                       "r.fecha_inicio_realizacion, r.fecha_fin_realizacion, p.descripcion_prueba " + 
                "FROM " + this.schema + ".ronda r INNER JOIN  " + this.schema + ".prueba p " + 
                             "ON r.id_prueba = p.id_prueba " +
                             "INNER JOIN (SELECT ir.id_tipo_ronda, ir.id_prueba " +
                                        "FROM  " + this.schema + ".inscripcionRonda ir " +
                                        "WHERE ir.clasificacion IS NOT NULL " +
                                        "GROUP BY ir.id_tipo_ronda, ir.id_prueba) as ir " +
                             "ON p.id_prueba = ir.id_prueba AND r.id_tipo_ronda = ir.id_tipo_ronda " +
                             "LEFT OUTER JOIN " + 
                                 "(SELECT id_tipo_ronda, id_prueba, COUNT (id_usuario) participantes " +
                                 "FROM  " + this.schema + ".inscripcionRonda " +
                                 "WHERE fecha_presentacion is not null " +
                                 "GROUP BY id_tipo_ronda, id_prueba) as i " +
                             "ON r.id_tipo_ronda = i.id_tipo_ronda " + 
                             "AND r.id_prueba = i.id_prueba;";
            
            ResultSet rs = sentencia.executeQuery(consulta);
            while(rs.next()){
                PruebaDetalleEstadistico p = new PruebaDetalleEstadistico();
                p.setId_prueba(rs.getInt("id_prueba"));
                p.setId_tipo_ronda(rs.getInt("id_tipo_ronda"));
                p.setRespuestas(rs.getString("respuestas"));
                p.setParticipantes(rs.getInt("participantes"));
                p.setNumeroPreguntas(rs.getInt("numero_preguntas"));
                p.setFechaInicioRealizacion(rs.getDate("fecha_inicio_realizacion"));
                p.setFechaFinRealizacion(rs.getDate("fecha_fin_realizacion"));
                p.setDescripcionPrueba(rs.getString("descripcion_prueba"));
                p.setDescripcionTipoRonda(TipoRonda.values()[p.getId_tipo_ronda()].toString());
                pruebaDetalleEstadistico.add(p);
            }
            sentencia.close();
        }catch (SQLException e) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_ObtenerPruebas"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_ObtenerPruebas"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        }
        return pruebaDetalleEstadistico;
    }

    /**
     * Detalle de participantes de la ventana de detalles
     * @param iP (int id_prueba)
     * @param iTP (int id_tipo_ronda)
     * @param fD (String fecha_desde_presentacion -dd/MM/yyyy-)
     * @param fH (String fecha_hasta_presentacion -dd/MM/yyyy-)
     * @return List<ParticipantesEstadistica>
     * Se obtiene el detalle de participantes reales (con fecha de presentación distinta de nulo) 
     * de la prueba/tipo de prueba que se pasa por parámetro.
     * Las fechas remitidas son opcionales si se pasa alguna de ellas, filtra el resultado por las mismas.
     * Los datos devueltos son: el nombre y apellidos de los estudiantes, clasificación, nombre de la universidad,
     * fecha de la presentación, respuestas del estudiante, respuestas correctas y puntuación.
     * Con la respuesta correctas y del estudiante, mediante la función comparaRespuestas se obtienen los datos de 
     * respuestas acertadas, erronas y en blanco.
     * @throws RemoteException
     */
    public List<ParticipantesEstadistica> obtenerParticipantes(int iP, int iTP, String fD, String fH) throws RemoteException{
        List<ParticipantesEstadistica> listaParticipantes = new ArrayList<ParticipantesEstadistica>();
        try {
            Statement sentencia = this.remoto.getConexion().createStatement();
            String consulta =
                "SELECT TRIM(u.nombre || ' ' || u.apellido_primero) nombre_completo, u.apellido_segundo, " +  
                        "ir.clasificacion, nombre_universidad, ir.fecha_presentacion, ir.respuestas_estudiantes, " +
                        "r.respuestas, ir.puntuacion " +
                "FROM inscripcionRonda ir " +
                     "INNER JOIN usuario u " +
                     "ON ir.id_usuario = u.id_usuario " +
                     "INNER JOIN Universidad un " +
                     "ON u.id_universidad = un.id_universidad " +
                     "INNER JOIN ronda r " +
                     "ON ir.id_tipo_ronda = r.id_tipo_ronda AND ir.id_prueba = r.id_prueba " +
                "WHERE ir.id_tipo_ronda = " + iTP + " AND ir.id_prueba = " + iP +
                       "AND ir.fecha_presentacion IS NOT NULL";
                 if (!fD.equals("__/__/____")){
                    consulta = consulta + " AND '" + fD + "' <= ir.fecha_presentacion";
                 }
                 if (!fH.equals("__/__/____")){
                     consulta = consulta + " AND '" + fH + "' >= ir.fecha_presentacion";
                 }
                consulta = consulta + " ORDER BY ir.clasificacion ASC;";
            ResultSet rs = sentencia.executeQuery(consulta);
            while(rs.next()){
                ParticipantesEstadistica p = new ParticipantesEstadistica();
                p.setNombreCompleto(rs.getString("nombre_completo"));
                String ape2 = rs.getString("nombre_completo");
                if (ape2 != null){p.setNombreCompleto ( p.getNombreCompleto() + " " + ape2);}
                p.setClasificacion(rs.getInt("clasificacion"));
                p.setUniversidad(rs.getString("nombre_universidad"));
                p.setFechaPresentacion(rs.getDate("fecha_presentacion"));
                String respEstudiante = rs.getString("respuestas_estudiantes");
                String respCorrecta = rs.getString("respuestas");
                p.setPuntuacion(rs.getDouble("puntuacion"));
                numAciertos = 0;
                numBlancos = 0;
                numErrores = 0;
                numPreguntas = 0;

                if (comparaRespuestas(respEstudiante, respCorrecta, 0)){
                    p.setAciertos(numAciertos);
                    p.setFallos(numErrores);
                    p.setEnBlaco(numBlancos);
                } 
                listaParticipantes.add(p);
            }
            sentencia.close();
        }catch (SQLException e) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.sql_ObtenerParticipantes"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("GestorEstadistica.indeterminado_ObtenerParticipantes"), GestorIdiomas.getMessage("ShowMessageDialog.Error"), 0);
        }
            return listaParticipantes;
    }
     
   /**
     * 
     * @param String cadena de respuesta
     * @param String cadena correcta
     * @param int número de preguntas
     * @return boolean 
     * @throws RemoteException
     * En las variables del gestor de estadistica  numAciertos, numBlancos, numErrores y numPreguntas
     * devuelve los mencionados valores resultados de comparar las dos cadenas
     */
    private boolean comparaRespuestas(String cE, String cC, int nPO){
        boolean salida = false;
        //Sólo pasa por aqui si las cadenas de 'respuestas' y 'respuestas de estudiantes' son disntintas de nulo                
        if (cC != null && cE != null) {
            char[] cRC = cC.toCharArray();
            char[] cRE = cE.toCharArray();
            int nP = 0;
            //Si las cadenas a comparar tienen distinto tamaño se toma como el número de caracteres a comparar el de la menor
            if(cRC.length < cRE.length) {nP = cRC.length;} else {nP = cRE.length;}
            if (nPO>0){
                if (nPO<nP){nP=nPO;}
            }
            if(nP >0){salida=true;}
            for(int c = 0; c < nP; c = c + 1){
                numPreguntas++;
                if(cRC[c]==cRE[c]){
                    numAciertos++;
                }
                else{
                    if(cRE[c] == ' ' || cRE[c] == '0'){numBlancos++;} else {numErrores++;} 
                }
            }
        }
        return salida;
    }
 }
